<!doctype html>
<html lang="en">

<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Todo List</title>
	<link rel="stylesheet" href="assets/css/base.css">
	<link rel="stylesheet" href="assets/css/index.css">
	<link rel="stylesheet" href="/js/nprogress/nprogress.css">
</head>

<body>
	<section class="todoapp">
		<header class="header">
			<h1>todos</h1>
			<input type="text" class="new-todo" placeholder="What needs to be done?" autofocus id="task">
		</header>
		<!-- This section should be hidden by default and shown when there are todos -->
		<section class="main">
			<input class="toggle-all" type="checkbox">
			<ul class="todo-list" id="todo-list"></ul>
		</section>
		<!-- This footer should hidden by default and shown when there are todos -->
		<footer class="footer">
			<!-- This should be `0 items left` by default -->
			<span class="todo-count"><strong id="count">0</strong> item left</span>
			<!-- Remove this if you don't implement routing -->
			<ul class="filters">
				<li>
					<a class="selected" id="all" href="javascript:;">All</a>
				</li>
				<li>
					<a id="active" href="javascript:;">Active</a>
				</li>
				<li>
					<a id="completed" href="javascript:;">Completed</a>
				</li>
			</ul>
			<!-- Hidden if no completed items are left ↓ -->
			<button class="clear-completed">Clear completed</button>
		</footer>
	</section>
	<script src="/js/jquery.min.js"></script>
	<script src="/js/template-web.js"></script>
	<script src="/js/nprogress/nprogress.js"></script>

	<!-- 任务列表模板 -->
	<script type="text/html" id="taskTpl">
		{{each tasks}}
		<li class="{{$value.completed ? 'completed' : ''}}">
			<div class="view">
				<input class="toggle" type="checkbox" {{$value.completed ? 'checked' : ''}}>
				<label>{{$value.title}}</label>
				<button class="destroy" data-id="{{$value._id}}"></button>
			</div>
			<input class="edit">
		</li>
		{{/each}}
	</script>

	<script>
		// 用于存放任务列表的数组
		var taskAry = [];
		// 选择任务列表容器
		var taskBox = $('#todo-list');
		// 添加任务的文本框
		var taskInp = $('#task');
		// 用于存储未完成任务数量的strong标签
		var strong = $('#count');
		// 显示所有的任务的按钮
		var all = $('#all');
		// 显示未完成的任务的按钮
		var active = $('#active');
		// 显示已完成的任务的按钮
		var completed = $('#completed');
		// 清除已完成任务的按钮
		var clearCompleted = $('.clear-completed');

		// 当页面中有ajax请求发送时触发
		$(document).on('ajaxStart', function () {
			// 进度条开始运动 
			NProgress.start();
		});

		// 当页面中有ajax请求完成时触发
		$(document).on('ajaxComplete', function () {
			// 进度条结束运动
			NProgress.done();
		});

		/* 		
		功能1：展示任务列表
		 */
		// 向服务器端发送请求 获取已经存在的任务
		$.ajax({
			url: '/todo/task',
			type: 'get',
			success: function (response) {
				// 将已存在的任务存储在taskAry变量中
				taskAry = response;
				// 拼接字符串 将拼接好的字符串显示在页面中
				render();
				// 计算未完成任务数量
				calcCount();
			}
		});

		// 拼接字符串 将拼接好的字符串显示在页面中
		function render() {
			// 字符串拼接
			var html = template('taskTpl', { tasks: taskAry });
			// 将拼接好的字符串显示在ul标签中
			taskBox.html(html);
		}

		/* 		
		功能2：添加任务
		 */
		// 获取文本框并且添加键盘抬起事件
		taskInp.on('keyup', function (event) {
			// 如果用户敲击的是回车键
			if (event.keyCode == 13) {
				// 判断用户是否在文本框中输入了任务名称   
				var taskName = $(this).val();
				// 如果用户没有在文本框中输入内容
				if (taskName.trim().length == 0) {
					alert('请输入任务名称');
					// 阻止代码向下执行
					return;
				}
				// 向服务器端发送请求 添加任务
				$.ajax({
					type: 'post',
					url: '/todo/addTask',
					contentType: 'application/json',
					data: JSON.stringify({ title: taskName }),
					success: function (response) {
						// 将任务添加到任务列表中
						taskAry.push(response);
						// 拼接字符串 将拼接好的字符串显示在页面中
						render();
						// 清空文本框中的内容
						taskInp.val('');
						// 计算未完成任务数量
						calcCount();
					}
				});
			}
		});

		/*
		功能3：删除任务
		 */
		// 当用户点击删除按钮时触发ul标签身上的点击事件
		taskBox.on('click', '.destroy', function () {
			// 要删除的任务的id
			var id = $(this).attr('data-id');
			// 向服务器端发送请求删除任务
			$.ajax({
				type: 'get',
				url: '/todo/deleteTask',
				data: {
					_id: id
				},
				success: function (response) {
					// 从任务数组中找到已经删除掉的任务的索引
					var index = taskAry.findIndex(item => item._id == id);
					// 将任务从数组中删除
					taskAry.splice(index, 1);
					// 重新将任务数组中的元素显示在页面中
					render();
					// 计算未完成任务数量
					calcCount();
				}
			})
		});

		/*
		功能4：更改任务状态
		 */
		// 当用户改变任务名称前面的复选框状态时触发
		taskBox.on('change', '.toggle', function () {
			// 代表复选框是否选中 true 选中 false 未选中的
			const status = $(this).is(':checked');
			// 当前点击任务的id
			const id = $(this).siblings('button').attr('data-id');
			// 向服务器端发送请求 更改任务状态
			$.ajax({
				type: 'post',
				url: '/todo/modifyTask',
				data: JSON.stringify({ _id: id, completed: status }),
				contentType: 'application/json',
				success: function (response) {
					// 将任务状态同步到任务数组中
					var task = taskAry.find(item => item._id == id);
					// 更改任务状态
					task.completed = response.completed;
					// 将数组中任务的最新状态更新到页面中
					render();
					// 计算未完成任务数量
					calcCount();
				}
			})
		});

		/*
		功能5：修改任务名称
		 */
		// 当双击事件名称的时候触发
		taskBox.on('dblclick', 'label', function () {
			// 让任务处于编辑状态
			$(this).parent().parent().addClass('editing');
			// 将任务名称显示在文本框中
			$(this).parent().siblings('input').val($(this).text());
			// 让文本框获取焦点
			$(this).parent().siblings('input').focus();
		});

		// 当文本框离开焦点时，将用户在文本框中输入值提交到服务器端，并且将最新的任务名称更新到任务列表数组中
		taskBox.on('blur', '.edit', function () {
			// 最新的任务名称
			var newTaskName = $(this).val();
			// 编辑任务的id
			var id = $(this).siblings().find('button').attr('data-id');
			// 向服务器端发送请求 修改任务名称
			$.ajax({
				type: 'post',
				url: '/todo/modifyTask',
				data: JSON.stringify({ _id: id, title: newTaskName }),
				contentType: 'application/json',
				success: function (response) {
					// 将当期任务的最新状态同步到任务数组中
					var task = taskAry.find(item => item._id == id);
					// 修改任务名称
					task.title = response.title;
					// 将任务数组中的任务同步到页面中
					render();
					// 计算未完成任务数量
					calcCount();
				}
			});
		});

		/*
		功能6：计算未完成任务数量
		 */
		// 用于计算未完成任务的数量
		function calcCount() {
			// 存储结果的变量
			var count = 0;
			// 将未完成的任务过滤到一个新的数组中
			var newAry = taskAry.filter(item => item.completed == false);
			// 将新数组的长度赋值给count
			count = newAry.length;
			// 将未完成的任务数量显示在页面中
			strong.text(count);
		};

		/*
		功能7：显示所有的任务
		 */
		all.on('click', function () {
			render();
		});

		/*
		功能8：显示未完成的任务的按钮
		 */
		active.on('click', function () {
			// 未完成任务的数组
			var waitTaskAry = taskAry.filter(item => item.completed == false);
			// 字符串拼接
			var html = template('taskTpl', { tasks: waitTaskAry });
			// 将拼接好的字符串显示在ul标签中
			taskBox.html(html);
		});

		/*
		功能9：显示已完成的任务的按钮
		 */
		completed.on('click', function () {
			// 已完成任务的数组
			var completedTaskAry = taskAry.filter(item => item.completed == true);
			// 字符串拼接
			var html = template('taskTpl', { tasks: completedTaskAry });
			// 将拼接好的字符串显示在ul标签中
			taskBox.html(html);
			// 存储结果的变量
			var count = 0;
			// 将未完成的任务过滤到一个新的数组中
			var newAry = taskAry.filter(item => item.completed == true);
			// 将新数组的长度赋值给count
			count = newAry.length;
			// 将未完成的任务数量显示在页面中
			strong.text(count);
		});

		/*
		功能10：清除已完成任务的按钮
		 */
		clearCompleted.on('click', function () {
			$.ajax({
				type: 'get',
				url: '/todo/clearTask',
				success: function (response) {
					// 未完成任务的数组
					var ary = taskAry.filter(item => item.completed == false);
					// 把未完成任务的数组赋值给taskAry（将任务列表中的已完成任务删除调用）
					taskAry = ary;
					// 重新将任务数组中的元素显示在页面中
					render();
					// 计算未完成任务数量
					calcCount();
				}
			});
		});

	</script>
</body>

</html>